﻿using System;
using System.ComponentModel;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using BigMailer.Client.Services;
using Microsoft.Win32;
using System.Collections.Generic;
using System.IO;
using System.Deployment.Application;
using System.Diagnostics;
using BigMailer.Client;

namespace BigMailer
{
	public partial class MainWindow : Window
	{
		private SynchronizationContext syncCtx;

		public MainWindow()
		{
			InitializeComponent();

			syncCtx = SynchronizationContext.Current;
			LoadExistingFilesAsync();
			CheckForNewVersionAsync();
			WarnOnDelete = true;
		}

		private bool IsServerConfigured
		{
			get { return !string.IsNullOrEmpty( UiCore.ServiceUrl ); }
		}

		public static bool WarnOnDelete { get; set; }

		private string MyVersion
		{
			get { return this.GetType().Assembly.GetName().Version.ToString(); }
		}

		private void LoadExistingFilesAsync()
		{
			ThreadPool.QueueUserWorkItem( delegate 
			{
				Trace.WriteLine( "Mailer: Loading existing files from svc." );
				if ( string.IsNullOrEmpty( UiCore.ServiceUrl ) )
				{
					Trace.WriteLine( "Mailer: Svc is not configured, cancelled." );
					return;
				}

				try
				{
					ExistingFile[] files;
					using ( MailerClient client = new MailerClient(UiCore.ServiceUsername, UiCore.ServicePassword, UiCore.ServiceUrl) )
					{
						files = client.GetPreexistingFiles();
					}

					if (files.Length == 0)
                    {
						Trace.WriteLine( "Mailer: No existing files found." );
						return;
                    }

					syncCtx.Post(
						delegate
						{
							if ( files.Length > 0 )
							{
								ExistingHeadeControl ctrl = new ExistingHeadeControl();
								listBoxUploads.Items.Add( ctrl );
							}

							foreach ( ExistingFile file in files )
							{
								ExistingFileControl ctrl = new ExistingFileControl( file );
								ctrl.Deleted += ctrl_Deleted;
								listBoxUploads.Items.Add( ctrl );
							}

							Trace.WriteLine( "Mailer: Existing files loaded." );
						}, null );
				}
				catch ( Exception ex )
				{
					MessageBox.Show( "Error contacting service for existing files:\n\n" + ex.Message, "Service Error",
									 MessageBoxButton.OK,
									 MessageBoxImage.Error );
					Trace.WriteLine( "Mailer: Error getting files: " + ex );
					return;
				}
			} );
		}

		private void CheckForNewVersionAsync()
		{
			ThreadPool.QueueUserWorkItem( delegate
          	{
				Trace.WriteLine( "Mailer: Checking for new version..." );
          		if ( !ApplicationDeployment.IsNetworkDeployed )
          		{
					Trace.WriteLine( "Mailer: Application is not network deployed, cancelled." );
          			return;
          		}

          		if ( !ApplicationDeployment.CurrentDeployment.CheckForUpdate() )
          		{
					Trace.WriteLine( "Mailer: No updateds, you have the current version." );
          			return;
          		}

				Trace.WriteLine( "Mailer: An update has been found.");

          		syncCtx.Post(
      				delegate {
						string msg = "There is a new version of this application available. Do you want to download the new version?";
						string cap = this.Title;
						if (MessageBox.Show(msg, cap, MessageBoxButton.YesNoCancel, MessageBoxImage.Question) == MessageBoxResult.Yes)
						{
							ApplicationDeployment.CurrentDeployment.Update();
							MessageBox.Show(
								"Update complete: Please relaunch the application to use the new version.",
								cap, MessageBoxButton.OK, MessageBoxImage.Information );

							this.Close();
						}
      				}, null
      				);
          	}, null);
		}

		private void ctrl_Deleted(object sender, EventArgs e)
		{
			listBoxUploads.Items.Remove( sender );
		}

		private void buttonUpload_Click(object sender, RoutedEventArgs e)
		{
			if ( !IsServerConfigured )
			{
				MessageBox.Show( "You must first configure the server url.", "Mailer: Just a second now...", MessageBoxButton.OK,
				                 MessageBoxImage.Stop );
				return;
			}

			try
			{
				using ( MailerClient client = new MailerClient( UiCore.ServiceUsername, UiCore.ServicePassword, UiCore.ServiceUrl ) )
				{
					client.Ping();
				}
			}
			catch ( Exception ex )
			{
				MessageBox.Show( "Error contacting service: " + ex, "Service Error", MessageBoxButton.OK, MessageBoxImage.Error );
				return;
			}

			OpenFileDialog dialog = new OpenFileDialog();
			dialog.Multiselect = true;
			bool? res = dialog.ShowDialog( this );
			if ( res == null || !(bool)res )
			{
				return;
			}

			foreach ( string file in dialog.FileNames )
			{
				listBoxUploads.Items.Insert( 0, new UploadingControl( file ) );
			}
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			if ( !string.IsNullOrEmpty( UiCore.ServiceUrl ) )
			{
				glowEffectConfig.GlowColor = Colors.White;
				glowEffectSave.GlowColor = Colors.White;
			}
		}

		private void Window_Closing(object sender, CancelEventArgs e)
		{
			foreach ( Control control in listBoxUploads.Items )
			{
				UploadingControl upCtrl = control as UploadingControl;
				if ( upCtrl == null )
				{
					return;
				}

				try
				{
					upCtrl.Dispose();
				}
				catch ( Exception )
				{
				}
			}
		}

		private void linkConfigure_Click(object sender, RoutedEventArgs e)
		{
			UrlWindow window = new UrlWindow();
			window.Url = UiCore.ServiceUrl;
			window.UserName = UiCore.ServiceUsername;
			window.Password = UiCore.ServicePassword;
			window.Owner = this;

			if ( window.ShowDialog().Value )
			{
				UiCore.ServiceUrl = window.Url;
				UiCore.ServiceUsername = window.UserName;
				UiCore.ServicePassword = window.Password;
			}
		}

		private void linkAbout_Click(object sender, RoutedEventArgs e)
		{
			string msg =
				"Created by Michael Kennedy\nwww.michaelckennedy.net\n" +
				"Version: " + MyVersion + "\n" +
				"\n" +
				"This project is hosted on CodePlex: http://www.codeplex.com/bigmailer";

			MessageBox.Show( msg, "About", MessageBoxButton.OK, MessageBoxImage.Information );
		}

		private void linkSaveServerCode_Click(object sender, RoutedEventArgs e)
		{
			UiCore.SaveHostCode();
		}

		private void Window_DragEnter(object sender, DragEventArgs e)
		{
			List<string> formats = new List<string>( e.Data.GetFormats() );

			if ( formats.Contains( DragDropConstants.FileDrop ) )
			{
				e.Effects = DragDropEffects.Copy;
			}
			else
			{
				e.Effects = DragDropEffects.None;
			}
		}

		private void Window_Drop(object sender, DragEventArgs e)
		{
			if ( !IsServerConfigured )
			{
				MessageBox.Show( "You must first configure the server url.", "Mailer: Just a second now...", MessageBoxButton.OK,
								 MessageBoxImage.Stop );
				return;
			}

			string[] files = (string[])e.Data.GetData( DragDropConstants.FileDrop );

			foreach ( string file in files )
			{
				listBoxUploads.Items.Insert( 0, new UploadingControl( file ) );	
			}			
		}

		private void MoveCompletedFilesToExistingFiles()
		{
			RemoveCompletedItems();
			List<string> pendingFiles = GetActiveFiles();

			ExistingFile[] files;
			using ( MailerClient client = new MailerClient( UiCore.ServiceUsername, UiCore.ServicePassword, UiCore.ServiceUrl ) )
			{
				files = client.GetPreexistingFiles();
			}

			if ( files.Length > 0 )
			{
				ExistingHeadeControl ctrl = new ExistingHeadeControl();
				listBoxUploads.Items.Add( ctrl );
			}

			foreach ( ExistingFile file in files )
			{
				if (pendingFiles.Contains(file.Name.ToLower()))
				{
					continue;
				}

				ExistingFileControl ctrl = new ExistingFileControl( file );
				ctrl.Deleted += ctrl_Deleted;
				listBoxUploads.Items.Add( ctrl );
			}
		}

		private List<string> GetActiveFiles()
		{
			List<string> items = new List<string>();
			foreach ( object item in listBoxUploads.Items )
			{
				if ( item is UploadingControl )
				{
					UploadingControl ctrl = (UploadingControl)item;
					if ( ctrl.Status == SendStatus.Active )
					{
						items.Add( Path.GetFileName( ctrl.FileName ).ToLower() );
					}
				}
			}

			return items;
		}

		private void RemoveCompletedItems()
		{
			List<object> items = new List<object>();
			foreach ( object item in listBoxUploads.Items )
			{
				items.Add( item );
			}

			foreach ( object item in items )
			{
				if ( item is ExistingFileControl )
				{
					listBoxUploads.Items.Remove( item );
				}
				else if ( item is ExistingHeadeControl )
				{
					listBoxUploads.Items.Remove( item );
				}
				else if ( item is UploadingControl )
				{
					UploadingControl ctrl = (UploadingControl)item;
					if ( ctrl.Status == SendStatus.Cancelled ||
						ctrl.Status == SendStatus.Uploaded )
					{
						listBoxUploads.Items.Remove( item );
						ctrl.Dispose();
					}
				}
			}
		}

		private void refreshLink_Click(object sender, RoutedEventArgs e)
		{
			MoveCompletedFilesToExistingFiles();
		}

		private void disableDeleteLink_Click(object sender, RoutedEventArgs e)
		{
			WarnOnDelete = !WarnOnDelete;
			UpdateUi();
		}

		private void UpdateUi()
		{
			disableDeleteBlock.Visibility = WarnOnDelete ? Visibility.Visible : Visibility.Collapsed;
			enableDeleteBlock.Visibility = WarnOnDelete ? Visibility.Collapsed : Visibility.Visible;
		}
	}
}